﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using MoneyManagerNET.Model;

namespace App
{
    /// <summary>
    ///   Facade on EntityBus
    /// </summary>
    public static class Storage
    {
        private static readonly TraceSource trace;
        private static readonly IEntityBus implementation;

        static Storage()
        {
            trace = new TraceSource("storage");

            trace.TraceEvent(TraceEventType.Start, 0, "Setting up implementation");
            Trace.Indent();

            // Load repository from settings, use in-memory mock as fallback
            implementation = new EntityBusLoader().LoadEntityBus();

            Trace.Unindent();
            trace.TraceEvent(TraceEventType.Stop, 0, "Done: Setting up implementation");
        }

        public static IEnumerable<TEntity> Select<TEntity>(Func<TEntity, bool> where) where TEntity : class
        {
            return implementation.Select(where);
        }

        public static IEnumerable<TEntity> Select<TEntity>() where TEntity : class
        {
            trace.TraceInformation("Select {0}", typeof (TEntity).Name);
            try
            {
                return Select<TEntity>(null);
            }
            catch (Exception exp)
            {
                trace.TraceEvent(TraceEventType.Error, 0, "Select : {0}", exp.Message);
                throw;
            }
        }

        public static TEntity New<TEntity>() where TEntity : class
        {
            trace.TraceInformation("New {0}", typeof (TEntity).Name);
            try
            {
                return implementation.New<TEntity>();
            }
            catch (Exception exp)
            {
                trace.TraceEvent(TraceEventType.Error, 0, "New : {0}", exp.Message);
                throw;
            }
        }

        public static void SaveAll()
        {
            trace.TraceInformation("SaveAll");

            try
            {
                implementation.SaveAll();
            }
            catch (Exception exp)
            {
                trace.TraceEvent(TraceEventType.Error, 0, "SaveAll : {0}", exp.Message);
                throw;
            }
        }

        public static void Reset()
        {
            trace.TraceInformation("Reset");
            try
            {
                implementation.Reset();
            }
            catch (Exception exp)
            {
                trace.TraceEvent(TraceEventType.Error, 0, "Reset : {0}", exp.Message);
                throw;
            }
        }

        public static void Delete<TEntity>(TEntity entity) where TEntity : class
        {
            trace.TraceInformation("Delete {0}", typeof (TEntity).Name);
            try
            {
                implementation.Delete(entity);
            }
            catch (Exception exp)
            {
                trace.TraceEvent(TraceEventType.Error, 0, "Delete : {0}", exp.Message);
                throw;
            }
        }
    }
}